import { Injectable, Logger } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import {
  SystemMessageEntity,
  SystemMessageType,
} from "../entities/system-message.entity";

/**
 * 系统消息服务
 * 负责保存和管理系统消息，包括个人消息和广播消息
 */
@Injectable()
export class SystemMessageService {
  private readonly logger = new Logger(SystemMessageService.name);

  constructor(
    @InjectRepository(SystemMessageEntity)
    private readonly systemMessageRepository: Repository<SystemMessageEntity>
  ) {}

  /**
   * 解析消息体为对象
   * @param messageBody 消息体（字符串或对象）
   * @returns 解析后的对象
   */
  private parseMessageBody(messageBody: any): any {
    if (typeof messageBody === "string") {
      try {
        return JSON.parse(messageBody);
      } catch (error: any) {
        this.logger.warn(`解析消息体失败，返回原始字符串: ${error?.message}`);
        return messageBody;
      }
    }
    return messageBody;
  }

  /**
   * 批量解析消息列表的messageBody
   * @param messages 消息列表
   * @returns 解析后的消息列表
   */
  private parseMessages(
    messages: SystemMessageEntity[]
  ): SystemMessageEntity[] {
    return messages.map((message) => ({
      ...message,
      messageBody: this.parseMessageBody(message.messageBody),
    }));
  }

  /**
   * 保存广播消息
   * @param messageBody 消息体（完整的广播消息格式，对象或字符串）
   * @param senderId 发送者ID，默认为0（系统）
   * @param senderName 发送者名称，默认为"系统"
   * @returns 保存的消息实体（messageBody已解析为对象）
   */
  async saveBroadcastMessage(
    messageBody: any,
    senderId: number = 0,
    senderName: string = "系统"
  ): Promise<SystemMessageEntity> {
    try {
      const systemMessage = new SystemMessageEntity();

      // 设置基本信息
      systemMessage.senderId = senderId;
      systemMessage.senderName = senderName;
      // 统一格式化：存储时转换为字符串
      systemMessage.messageBody = JSON.stringify(messageBody);
      systemMessage.messageType = SystemMessageType.BROADCAST;
      systemMessage.receiverId = null; // 广播消息接收者为空
      systemMessage.isRead = 1; // 广播消息默认已读

      // 保存到数据库
      const savedMessage = await this.systemMessageRepository.save(
        systemMessage
      );

      // 返回时解析messageBody为对象
      savedMessage.messageBody = JSON.parse(savedMessage.messageBody);

      this.logger.log(`✅ 成功保存广播消息，ID: ${savedMessage.id}`);

      return savedMessage;
    } catch (error: any) {
      this.logger.error(`❌ 保存广播消息失败:`, error?.message || error);
      throw error;
    }
  }

  /**
   * 保存个人消息
   * @param messageBody 消息体（完整的个人消息格式，对象或字符串）
   * @param receiverId 接收者ID
   * @param senderId 发送者ID，默认为0（系统）
   * @param senderName 发送者名称，默认为"系统"
   * @returns 保存的消息实体（messageBody已解析为对象）
   */
  async savePersonalMessage(
    messageBody: any,
    receiverId: number,
    senderId: number = 0,
    senderName: string = "系统"
  ): Promise<SystemMessageEntity> {
    try {
      const systemMessage = new SystemMessageEntity();

      // 设置基本信息
      systemMessage.senderId = senderId;
      systemMessage.senderName = senderName;
      // 统一格式化：存储时转换为字符串
      systemMessage.messageBody = JSON.stringify(messageBody);
      systemMessage.messageType = SystemMessageType.PERSONAL;
      systemMessage.receiverId = receiverId;
      systemMessage.isRead = 0; // 个人消息默认未读

      // 保存到数据库
      const savedMessage = await this.systemMessageRepository.save(
        systemMessage
      );

      // 返回时解析messageBody为对象
      savedMessage.messageBody = JSON.parse(savedMessage.messageBody);

      this.logger.log(
        `✅ 成功保存个人消息，ID: ${savedMessage.id}，接收者: ${receiverId}`
      );

      return savedMessage;
    } catch (error: any) {
      this.logger.error(`❌ 保存个人消息失败:`, error?.message || error);
      throw error;
    }
  }

  /**
   * 保存大小开奖广播消息
   * @param broadcastMessage 广播消息
   * @param roundId 期数ID
   * @returns 保存的消息实体
   */
  async saveDiceResultMessage(
    broadcastMessage: any,
    roundId: number
  ): Promise<SystemMessageEntity> {
    return this.saveBroadcastMessage(broadcastMessage);
  }

  /**
   * 保存赤壁开奖广播消息
   * @param broadcastMessage 广播消息
   * @param roundId 期数ID
   * @returns 保存的消息实体
   */
  async saveChibiResultMessage(
    broadcastMessage: any,
    roundId: number
  ): Promise<SystemMessageEntity> {
    return this.saveBroadcastMessage(broadcastMessage);
  }

  /**
   * 查询系统消息历史
   * @param messageType 消息类型（可选）
   * @param limit 限制数量
   * @param offset 偏移量
   * @returns 消息列表
   */
  async getSystemMessageHistory(
    messageType?: SystemMessageType,
    limit: number = 50,
    offset: number = 0
  ): Promise<SystemMessageEntity[]> {
    try {
      const queryBuilder = this.systemMessageRepository
        .createQueryBuilder("message")
        .orderBy("message.created_at", "DESC")
        .limit(limit)
        .offset(offset);

      if (messageType !== undefined) {
        queryBuilder.where("message.messageType = :messageType", {
          messageType,
        });
      }

      const messages = await queryBuilder.getMany();

      this.logger.log(`查询到 ${messages.length} 条系统消息`);
      return this.parseMessages(messages);
    } catch (error: any) {
      this.logger.error("查询系统消息历史失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 查询广播消息历史
   * @param limit 限制数量
   * @param offset 偏移量
   * @returns 广播消息列表
   */
  async getBroadcastMessageHistory(
    limit: number = 50,
    offset: number = 0
  ): Promise<SystemMessageEntity[]> {
    try {
      const messages = await this.systemMessageRepository
        .createQueryBuilder("message")
        .where("message.messageType = :messageType", {
          messageType: SystemMessageType.BROADCAST,
        })
        .orderBy("message.created_at", "DESC")
        .limit(limit)
        .offset(offset)
        .getMany();

      this.logger.log(`查询到 ${messages.length} 条广播消息`);
      return this.parseMessages(messages);
    } catch (error: any) {
      this.logger.error("查询广播消息历史失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 查询个人消息
   * @param receiverId 接收者ID
   * @param limit 限制数量
   * @param offset 偏移量
   * @returns 个人消息列表
   */
  async getPersonalMessages(
    receiverId: number,
    limit: number = 50,
    offset: number = 0
  ): Promise<SystemMessageEntity[]> {
    try {
      const messages = await this.systemMessageRepository
        .createQueryBuilder("message")
        .where("message.messageType = :messageType", {
          messageType: SystemMessageType.PERSONAL,
        })
        .andWhere("message.receiverId = :receiverId", { receiverId })
        .orderBy("message.created_at", "DESC")
        .limit(limit)
        .offset(offset)
        .getMany();

      this.logger.log(
        `查询到 ${messages.length} 条个人消息，接收者: ${receiverId}`
      );
      return this.parseMessages(messages);
    } catch (error: any) {
      this.logger.error(
        `查询个人消息失败，接收者: ${receiverId}:`,
        error?.message || error
      );
      throw error;
    }
  }

  /**
   * 将某角色的所有个人系统消息批量标记为已读
   */
  async markAllPersonalAsRead(receiverId: number): Promise<number> {
    try {
      const result = await this.systemMessageRepository
        .createQueryBuilder()
        .update(SystemMessageEntity)
        .set({ isRead: 1 })
        .where("receiverId = :receiverId", { receiverId })
        .andWhere("messageType = :messageType", {
          messageType: SystemMessageType.PERSONAL,
        })
        .andWhere("isRead = :isRead", { isRead: 0 })
        .execute();
      return result.affected || 0;
    } catch (error: any) {
      this.logger.error("批量标记个人系统消息已读失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 标记消息为已读
   * @param messageId 消息ID
   * @param receiverId 接收者ID（用于验证权限）
   * @returns 是否成功
   */
  async markAsRead(messageId: number, receiverId: number): Promise<boolean> {
    try {
      const result = await this.systemMessageRepository
        .createQueryBuilder()
        .update(SystemMessageEntity)
        .set({ isRead: 1 })
        .where("id = :messageId", { messageId })
        .andWhere("receiverId = :receiverId", { receiverId })
        .andWhere("messageType = :messageType", {
          messageType: SystemMessageType.PERSONAL,
        })
        .execute();

      const success = (result.affected || 0) > 0;
      if (success) {
        this.logger.log(
          `消息 ${messageId} 已标记为已读，接收者: ${receiverId}`
        );
      }
      return success;
    } catch (error: any) {
      this.logger.error(`标记消息为已读失败:`, error?.message || error);
      throw error;
    }
  }

  /**
   * 清理过期消息
   * @param days 保留天数
   * @returns 删除的消息数量
   */
  async cleanupExpiredMessages(days: number = 30): Promise<number> {
    try {
      const cutoffDate = new Date();
      cutoffDate.setDate(cutoffDate.getDate() - days);

      const result = await this.systemMessageRepository
        .createQueryBuilder()
        .delete()
        .where("created_at < :cutoffDate", { cutoffDate })
        .execute();

      const deletedCount = result.affected || 0;
      this.logger.log(`清理了 ${deletedCount} 条过期系统消息（${days}天前）`);

      return deletedCount;
    } catch (error: any) {
      this.logger.error("清理过期系统消息失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取消息类型名称
   * @param messageType 消息类型
   * @returns 类型名称
   */
  private getMessageTypeName(messageType: SystemMessageType): string {
    switch (messageType) {
      case SystemMessageType.PERSONAL:
        return "个人消息";
      case SystemMessageType.BROADCAST:
        return "广播消息";
      default:
        return "未知类型";
    }
  }

  /**
   * 获取指定用户的未读个人消息数量
   * @param receiverId 接收者ID
   * @returns 未读消息数量
   */
  async getUnreadPersonalMessageCount(receiverId: number): Promise<number> {
    try {
      const count = await this.systemMessageRepository.count({
        where: {
          messageType: SystemMessageType.PERSONAL,
          receiverId: receiverId,
          isRead: 0,
        },
      });

      return count;
    } catch (error: any) {
      this.logger.error(
        `获取未读个人消息数量失败，接收者: ${receiverId}:`,
        error?.message || error
      );
      return 0;
    }
  }

  /**
   * 获取指定用户的未读个人消息列表
   * @param receiverId 接收者ID
   * @param limit 限制数量，默认5条
   * @returns 未读个人消息列表
   */
  async getUnreadPersonalMessages(
    receiverId: number,
    limit: number = 5
  ): Promise<SystemMessageEntity[]> {
    try {
      const messages = await this.systemMessageRepository
        .createQueryBuilder("message")
        .where("message.messageType = :messageType", {
          messageType: SystemMessageType.PERSONAL,
        })
        .andWhere("message.receiverId = :receiverId", { receiverId })
        .andWhere("message.isRead = :isRead", { isRead: 0 })
        .orderBy("message.created_at", "DESC")
        .limit(limit)
        .getMany();

      this.logger.log(
        `查询到 ${messages.length} 条未读个人消息，接收者: ${receiverId}`
      );
      return this.parseMessages(messages);
    } catch (error: any) {
      this.logger.error(
        `获取未读个人消息失败，接收者: ${receiverId}:`,
        error?.message || error
      );
      return [];
    }
  }

  /**
   * 统计消息数量
   * @returns 各类型消息数量统计
   */
  async getMessageStatistics(): Promise<{
    total: number;
    personalMessages: number;
    broadcastMessages: number;
    unreadPersonalMessages: number;
  }> {
    try {
      const [
        total,
        personalMessages,
        broadcastMessages,
        unreadPersonalMessages,
      ] = await Promise.all([
        this.systemMessageRepository.count(),
        this.systemMessageRepository.count({
          where: { messageType: SystemMessageType.PERSONAL },
        }),
        this.systemMessageRepository.count({
          where: { messageType: SystemMessageType.BROADCAST },
        }),
        this.systemMessageRepository.count({
          where: {
            messageType: SystemMessageType.PERSONAL,
            isRead: 0,
          },
        }),
      ]);

      return {
        total,
        personalMessages,
        broadcastMessages,
        unreadPersonalMessages,
      };
    } catch (error: any) {
      this.logger.error("获取消息统计失败:", error?.message || error);
      throw error;
    }
  }
}
